#ifndef _VFX_DROPS_H_
#define _VFX_DROPS_H_

#include "sfx.h"
#include "background/bg_element.h"
#include "ui/ui_sprite.h"
#include "math/counter.h"
#include "editor/editor_brush.h"
#include "editor/editor_main.h"

namespace LuaPlus
{
	class LuaObject;
};

namespace vfx
{

class VFXDrops : public SFXSet
{
public:
	static const std::string	ELEMENT_NAME;

	VFXDrops(EffectMan* pParent = NULL);
	virtual ~VFXDrops();

	// call load to load variables from lua rather than setting up manually
	void						Load(const std::string& File);
	void						Load(LuaPlus::LuaObject& Obj);
	void						Save(script::WriteLua* pWL);

	// init is called once to setup sprite and particle info
	void						Init(const std::string& DropSprite, const std::string& SplashSprite = "", const std::string& DropPart = "", const std::string& SplashPart = "");
	void						Init(VFXDrops* pFrom);
	void						InitCache(int Size = 10);

	// setup can be called multiple times to change parameters of existing drops
	void						Setup(const math::Vec2& From, const math::Vec2& To, float Acceleration = 1.0f, float Frequency = 1.0f);
	void						SetWiggleZone(const math::Vec2& p) { m_WiggleZone = p; }
	void						SetRandomDelay(float f) { m_RandomDelay = f; }

	// clear all existing drops
	void						Clear();
	
	void						RenderDebug(const math::Vec2& Offset, float Scale = 1.0f);
	virtual	void				Render(const math::Vec2& Offset, float Scale);
	virtual void				Tick(float dt);

	void						GetBoundingBox(math::Vec2& From, math::Vec2& To);
	const std::string&			GetVFXName() { return m_VFXName; }

protected:
	int							CreateNewDrop(bool Alloc = true);
	void						DeleteDrop(int idx);
	//void						RenderSprite(ui::UISprite* pSprite, const math::Vec2& Pos, float Timer);

	math::Vec2					m_From, m_To, m_Dir;
	math::Vec2					m_WiggleZone;
	float						m_Acceleration;
	float						m_Frequency, m_Timer;
	float						m_RandomDelay, m_Delay;

	ui::UISprite				m_DropSprite, m_SplashSprite;
	std::string					m_DropPart, m_SplashPart;
	std::string					m_VFXName;
	part2d::Part2D*				m_pDropPart;
	part2d::Part2D*				m_pSplashPart;
	math::Vec2					m_DropSize, m_SplashSize;

	struct DROPLET
	{
		math::Vec2				Pos, Origin, To, Dir;
		float					Velocity, Acceleration;
		float					Time;

		//part2d::Part2D*			pDropPart;
		part2d::Part2D*			pSplashPart;

		math::Counter			SplashCounter;
		bool					HasSplashed;
		bool					IsAllocated;
	};

	std::vector<DROPLET>		m_Drops;
	int							m_AllocC;

	struct BATCH_RENDER
	{
		math::Vec2				Pos;
		float					Time;
	};
	inline void					BatchRender(std::vector<BATCH_RENDER>& Set, ui::UISprite* pSprite);
};

}; //namespace vfx


namespace background
{

class BGDropFX : public BGElement
{
public:
	BGDropFX(BGScene* pScene);
	virtual ~BGDropFX();

	virtual void			Render(const math::Vec2& Offset, float	Scale);
	virtual void			RenderDebug(const math::Vec2& Offset, float	Scale);
	virtual void			Tick(float dt);
	virtual void			Load(LuaPlus::LuaObject& Obj);
	virtual void			Save(script::WriteLua* pWL);
	virtual void			RecalcBoundingBox();
	virtual void			FlushImages();
	virtual const char*		GetName()  { return m_VFXDrops.GetVFXName().c_str(); }

	vfx::VFXDrops&			GetDropObj() { return m_VFXDrops; }
	void					Setup(vfx::VFXDrops* pFrom);

	static BGElement*		Create(BGScene* pScene);
	static void				RegisterMe(int KeyID);

protected:
	virtual	void			CopyData(BGElement*	pFrom);

	vfx::VFXDrops			m_VFXDrops;
};

}; //namespace background


namespace editor
{

class EditorMain;
class VFXDropBrush : public EditorBrush
{
public:
	VFXDropBrush(EditorMain* pEditor);
	virtual ~VFXDropBrush();

	virtual void				Render(const math::Vec2& Offset, float Scale);
	virtual void				Tick(float dt);
	virtual void				ReleaseLMB();
	virtual bool				TryDelete(const math::Vec2& Pos);
	virtual void				Raise(int Dir);
	virtual void				Rotate(int Dir);
	//virtual void				RenderHelp();

	void						LoadSet(const std::string& File);

	static EditorBrush*			Create(EditorMain* pMain);

private:
	void						RefreshHelpText();

	enum PLACE_STAGE
	{
		PLACE_ORIGIN,			// click to place origin (From)
		PLACE_DEST,				// click 2nd time to place destination (To)
		SET_PARAMS,				// move mouse around to determine parameters, and click 3rd time to finalize
								//      X-axis = frequency
								//      Y-axis = acceleration (gravity)
	};
	PLACE_STAGE					m_Stage;
	math::Vec2					m_From, m_To;
	float						m_Frequency, m_Acceleration;
	float						m_SortVal;

	std::vector<vfx::VFXDrops*>	m_Collection;
	background::BGDropFX*		m_pCurrent;
	int							m_CurrentIdx;
	background::BGScene*		m_pScene;
};

}; //namespace editor

#endif //_VFX_DROPS_H_
